LIBRARY ieee;
USE ieee.std_logic_1164.all;
USE ieee.numeric_std.all;
USE ieee.std_logic_unsigned.all;

ENTITY ScreenRecver IS
	PORT
	(
		Clk : IN std_logic;
		Reset : IN std_logic;
		Enable : IN std_logic;
		Rxd_RecvData : IN std_logic_vector(7 DOWNTO 0);
		RecvAvail : IN std_logic;
		--- Memory Port
		SecoAddr : OUT std_logic_vector(9 DOWNTO 0);
		SecoWriteData : OUT std_logic_vector(15 DOWNTO 0);
		SecoWriteEnable : OUT std_logic
	);
END ENTITY;

ARCHITECTURE rtl OF ScreenRecver IS
	TYPE State_Type IS (Idle, Init, Recv_Store_Pre ,Recv_Store, Recv_Store_Wait,Recv_Store_Finish, Recv_Wait0, Recv_Wait1, Recv_Wait2, Recv_Wait3);
	SIGNAL state : State_Type;
	SIGNAL DataCache : std_logic_vector(15 DOWNTO 0);
	SIGNAL PosX, PosY : std_logic_vector(4 DOWNTO 0);
	SIGNAL sCounter : std_logic_vector(2 DOWNTO 0);
BEGIN
	
	cMainCtl : PROCESS(Clk, Reset)
	BEGIN
		IF Reset = '0' THEN
			state <= Idle;
			PosX <= "00000" - 1;
			PosY <= "00001";
		ELSIF rising_edge(Clk) THEN
			CASE state IS
				WHEN Idle =>
					IF Enable = '1' THEN
						state <= Init;
					ELSE
						state <= Idle;
					END IF;
				WHEN Init =>
					state <= Recv_Wait3;
--				WHEN Recv_Wait0 =>
--					IF RecvAvail = '1' THEN
--						IF RxD_RecvData(7) = '1' THEN
--							PosX <= RxD_RecvData(5 downto 3) & "00";
--							PosY <= RxD_RecvData(2 downto 0) & "01";
--							state <= Recv_Wait0;
--						ELSE
--							-- Cache recvied data
--							DataCache(5 downto 0) <= RxD_RecvData(5 downto 0);
--							state <= Recv_Wait1;
--						END IF;
--					ELSE
--						state <= Recv_Wait0;
--					END IF;
--				WHEN Recv_Wait1 =>
--					IF RecvAvail = '1' THEN
--						IF RxD_RecvData(7) = '1' THEN
--							PosX <= RxD_RecvData(5 downto 3) & "00";
--							PosY <= Rxd_RecvData(2 downto 0) & "01";
--							state <= Recv_Wait0;
--						ELSE
--							-- Cache recvied data
--							DataCache(11 downto 6) <= RxD_RecvData(5 downto 0);
--							state <= Recv_Wait2;
--						END IF;
--					ELSE
--						state <= Recv_Wait1;
--					END IF;
--				WHEN Recv_Wait2 =>
--					IF RecvAvail = '1' THEN
--						IF RxD_RecvData(7) = '1' THEN
--							PosX <= RxD_RecvData(5 downto 3) & "00";
--							PosY <= Rxd_RecvData(2 downto 0) & "01";
--							state <= Recv_Wait0;
--						ELSE
--							-- Cache recvied data
--							DataCache(17 downto 12) <= RxD_RecvData(5 downto 0);
--							state <= Recv_Wait3;
--						END IF;
--					ELSE
--						state <= Recv_Wait2;
--					END IF;
				WHEN Recv_Wait3 =>
					IF RecvAvail = '1' THEN
						IF RxD_RecvData(7 downto 6) = "10" THEN
							PosX <= RxD_RecvData(5 downto 3) & "00" - 1;
							PosY <= Rxd_RecvData(2 downto 0) & "01";
							state <= Recv_Wait0;
						ELSE
							-- Cache recvied data
							DataCache(3 downto 0) <= RxD_RecvData(3 downto 0);
							-- Update Position
							IF PosX = 25 THEN
								
								IF PosY = 18 THEN
									PosX <= "00000";
									PosY <= "00001";
								ELSE
									PosX <= "00001";
									PosY <= PosY +1;
								END IF;
							ELSE
								PosX <= PosX +1;
							END IF;
							state <= Recv_Store_Pre;
						END IF;
					ELSE
						state <= Recv_Wait3;
					END IF;
				WHEN Recv_Store_Pre =>
					SecoAddr <= PosY & PosX;
					SecoWriteData <= DataCache;
					state <= Recv_Store;
				WHEN Recv_Store =>
					SecoWriteEnable <= '1';
					sCounter <= "000";
					state <= Recv_Store_Wait;
				WHEN Recv_Store_Wait =>
					IF(sCounter = 2)THEN
						SecoWriteEnable <= '0';
						state <= Recv_Store_Finish;
					ELSE
						sCounter <= sCounter + 1;
						state <= Recv_Store_Wait;
					END IF;
				WHEN Recv_Store_Finish =>
					state <= Recv_Wait3;
				WHEN OTHERS =>
					state <= Idle;
			END CASE;
		END IF;
	END PROCESS;
END rtl;
